#include "gtc_client.h"
#include "gtc_client_struct.h"
#include "gtc_client_pal.h"
#include "gtc_protocol.h"
#include "utility.h"
#include "log.h"
#include "crc16.h"

#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define LOGIN_TRUE          (1u)
#define LOGIN_FALSE         (0u)

#define SIGN_IN_TRUE            (1u)
#define SIGN_IN_FALSE           (0u)

#define MAX_BLOCKED_MQTT_RESP_NUM    (2u) 
#define MAX_GTC_INCIDENT_SUM         (3u)   //处理事件最大队列长度
#define MAX_GTC_INCIDENT_DATA_LEN    (300u) //事件数据最大长度

#define QOS_0     (0u)
#define QOS_1     (1u)
#define QOS_2     (2u)

enum GtcCmdType{
    gtc_cmd_type_null           = 0,               
	gtc_cmd_type_reconnection   = 1,    //  网络重连
    gtc_cmd_type_set_left_qr    = 2,    //  设置左枪二维码   
    gtc_cmd_type_set_righ_qr    = 3,    //  设置右枪二维码
    gtc_cmd_type_start_charge   = 4,    //  启动充电
    gtc_cmd_type_stop_charge    = 5,    //  停止充电
    gtc_cmd_type_set_time       = 6,    //  设置时间
    gtc_cmd_type_software_upgrade_cmd=7,    //软件升级命令
    gtc_cmd_type_software_upgrade_file=8,   //软件升级文件
    gtc_cmd_type_params_updated = 9,    //  参数更新
    gtc_cmd_type_upload_log     = 10,    //  上传日志
    gtc_cmd_type_control_cmd    = 11,   //   控制指令
    gtc_cmd_type_swip_card_ack  = 12,   //  刷卡应答
    
};

struct GtcCmdItem{
    enum GtcCmdType cmd;
    uint8_t data[MAX_GTC_INCIDENT_DATA_LEN+1];
    uint16_t len;
};

struct GtcCmdInfo{
    uint8_t sum;
    uint8_t cmd_new;  
    struct GtcCmdItem list[MAX_GTC_INCIDENT_SUM];
};

struct GtcMqttRespItem{
	int8_t submited;// 响应标志位
	uint8_t qos;
	enum GtcMqttCmdType cmd_type;
	char_t data[320];
};

struct GtcCalcBillInfoItem{
    uint32_t stop_charge_sec;
    uint32_t int_hour;
    uint32_t int_minute;
	int32_t index;
	uint32_t last_kwh;
	int32_t last_state;
	int32_t accum_kwh;
	uint32_t start_charge_sec;

};

struct GtcCalcBillInfoPara {
	int32_t sleeped_sec;
    struct GtcCalcBillInfoItem item[CHARGE_GUN_CNT];
};

struct GtcClientItem{
    struct GtcGunStatus gun_status_bak; //比较用，有变化就上传
    uint8_t is_reup; //每次签到后，重新上传枪状态信息
    uint32_t silent_send_gun_status_cnt; //10分钟主动上传一次状态
    struct GtcGunStatus gun_status;
    struct GtcBmsStatus bms_status;
    struct GtcBillInfo current_bill;
};

struct GtcClient{
    uint8_t is_login; //是否连接mqtt
    uint8_t is_signin; //是否签到
    uint32_t relogin_cnt; //重连计数
    
    struct GtcParams params; //需要保存的参数
    struct ClientUserGunInfo *user_gun_info; //设备端同步过来的枪参数
    struct ClientUserBmsInfo *user_bms_info; //设备端同步过来的bms参数
    struct GtcRecvProtBase recv_protocol; //接收到的消息集合
    struct GtcCmdInfo  cmd_info; //事件处理列表
    struct GtcMqttRespItem resp_queue[MAX_BLOCKED_MQTT_RESP_NUM]; //主动应答消息处理列表
    struct GtcHistroyBill histroy_bill[MAX_HISTORY_ORDER_CNT];
    
    struct GtcClientItem item[CHARGE_GUN_CNT]; //单个枪对应的信息
        
};


static struct GtcClient gtc_client;

static char_t system_storage = 0;
static struct GtcParams gtc_params ={0};
static struct T_updateInfo gtc_updateInfo={0};
static char_t gtc_recv_file_buf[1024]={0};    //升级数据存储用

void *gtc_mqtt_send_cmd(enum GtcMqttCmdType cmd_type, void * cmd, int32_t len, uint16_t time_out, uint8_t qos);
    

void get_gunnum_str(char_t gunnum, char_t *buf){
    sprintf(buf, "%s%02d", gtc_params.dev_id, gunnum);
}

static const char *get_sys_state_str(uint32_t state) {
    switch(state) {
    case gtc_work_stat_idle:
         return "idle";  
    case gtc_work_stat_charging:
        return "charge";
    case gtc_work_stat_in_error:
        return "alarm";
    default:
        break;
    }
    return NULL;
}

static const char_t *g_charge_type[4]={"auto", "power", "time", "money"};

static uint8_t get_charge_type_num(char_t *str){
	uint8_t num = 0;
	for(uint8_t i=0;i<sizeof(g_charge_type)/sizeof(char_t *);i++){
		if (strncmp(str, g_charge_type[i], strlen(g_charge_type[i]))){
			num = i;
			break;
		}
	}
	return num;	
}

static const char_t *get_charge_type_str(uint8_t type){
    if (type >= sizeof(g_charge_type)/sizeof(char_t *)){
        printf("get_charge_type_str type:%d err\r\n", type);
        type = 0;
    }
    return g_charge_type[type]; 
}

static uint8_t get_card_auth_ack_ret(char_t *str){
    uint8_t ret = CARD_AUTH_SUCC;
    if (strncmp(str, "succ", 4) == 0){
        ret = CARD_AUTH_SUCC;
    }else if (strncmp(str, "pwderr", 6) == 0){
        ret = CARD_AUTH_ERR_PWD;
    }else if (strncmp(str, "nomoney", 7) == 0){
        ret = CARD_AUTH_NO_MONEY;
    }else if (strncmp(str, "invaliduser", 11) == 0){
        ret = CARD_AUTH_INVALID_USER;
    }else if (strncmp(str, "admin", 5) == 0){
        ret = CARD_AUTH_ADMIN;
    }else{
        ret = CARD_AUTH_SUCC;
    }
    return ret;
}


#if 0 //发送消息打包
#endif

//签到报文
static void gtc_pack_sign_in_msg(char_t *buf) {
    char_t gun_type[10]={0};
    if (gtc_params.gun_type == gtc_gun_type_ac){
        strncpy(gun_type, "spac", 4);
    }else{
        strncpy(gun_type, "dc", 2);
    }
    
    set_cmd_str(buf, "cmd=", "init");
    set_cmd_str(buf, "&sno=", gtc_params.dev_id);
    set_cmd_str(buf, "&dtype=", gun_type);
    set_cmd_str(buf, "&ver=",SOFT_VERSION);  
    set_cmd_str(buf, "&subver=", "0");
    set_cmd_str(buf, "&costid=", "0");
    set_cmd_str(buf, "&encry=", "1");      //0未加密 1 关键协议加密 2 除了本条其他都加密
}

//设备状态
static void gtc_pack_dev_state_msg(struct GtcClientItem *item, char_t *buf) {
    set_cmd_str(buf, "cmd=", "state");
    set_cmd_str(buf, "&sno=", gtc_params.dev_id);
    char_t gunnum_str[32]={0};
    get_gunnum_str(item->gun_status.gun_id, gunnum_str);
    set_cmd_str(buf, "&subid=", gunnum_str);
    set_cmd_str(buf, "&gun=", (item->gun_status.car_connection_stat == gtc_gun_connected) ? "on" : "off");
    set_cmd_str(buf, "&sys=", get_sys_state_str(item->gun_status.work_stat));
    set_cmd_str(buf, "&alarm=", item->gun_status.alarm_code);
    set_cmd_float(buf, "&inv=", item->gun_status.ac_a_vol);
    set_cmd_float(buf, "&outv=", item->gun_status.dc_charge_voltage);
    set_cmd_float(buf, "&outa=", item->gun_status.dc_charge_current);
    set_cmd_float(buf, "&ackwh=", item->gun_status.current_meter_kwh_num);
    set_cmd_float(buf, "&ckw=", item->gun_status.charge_power_kw);
	set_cmd_value(buf, "&restt=", item->gun_status.left_time);
    set_cmd_value(buf, "&soc=", item->gun_status.soc_percent);
    set_cmd_float(buf, "&bmsnv=",item->gun_status.bms_need_voltage*10);
    set_cmd_float(buf, "&bmsnc=",item->gun_status.bms_need_current*10);

}

//bms信息
static void gtc_pack_bms_msg(struct GtcClientItem *item, char_t *buf) {
	set_cmd_str(buf, "cmd=", "bms");
	set_cmd_str(buf, "&sno=", gtc_params.dev_id);
	char_t gunnum_str[32]={0};
	get_gunnum_str(item->gun_status.gun_id, gunnum_str);
	set_cmd_str(buf, "&subid=", gunnum_str);
	set_cmd_str(buf, "&dno=", item->gun_status.order_id);
	set_cmd_bcd(buf, "&brmver=", item->bms_status.brm_bms_connect_version, GTC_MAX_BRM_BMS_CONNECT_VERSION_LEN);
	set_cmd_value(buf, "&brtype=", item->bms_status.brm_battery_type);
	set_cmd_value(buf, "&brmah=", item->bms_status.brm_battery_power);
	set_cmd_value(buf, "&brmv=", item->bms_status.brm_battery_volt);
	set_cmd_value(buf, "&brmmfrs=", item->bms_status.brm_battery_supplier);
	set_cmd_value(buf, "&brmno=", item->bms_status.brm_battery_seq);
	set_cmd_str(buf, "&brmtim=", "20000101"/*item->bms_status.brm_battery_produce_time*/);
	set_cmd_value(buf, "&brmcnt=", item->bms_status.brm_battery_charge_count);
	set_cmd_value(buf, "&brmr=", item->bms_status.brm_battery_property_identification);
	set_cmd_bcd(buf, "&brmvin=", item->bms_status.brm_vin, GTC_MAX_BRM_VIN_LEN);
	set_cmd_float(buf, "&bcpdv=", item->bms_status.bcp_max_voltage);
	set_cmd_float(buf, "&bcpa=", item->bms_status.bcp_max_current);
	set_cmd_float(buf, "&bcpkwh=", item->bms_status.bcp_max_power);
	set_cmd_float(buf, "&bcpcv=", item->bms_status.bcp_total_voltage);
	set_cmd_value(buf, "&bcpt=", item->bms_status.bcp_max_temperature);
	set_cmd_float(buf, "&bcpsoc=", item->bms_status.bcp_battery_soc);
	set_cmd_float(buf, "&bcpv=", item->bms_status.bcp_battery_soc_current_voltage);
	set_cmd_float(buf, "&bclv=", item->bms_status.bcl_voltage_need);
	set_cmd_float(buf, "&bclc=", item->bms_status.bcl_current_need);
	set_cmd_value(buf, "&bclm=", item->gun_status.bms_charge_mode);
	set_cmd_float(buf, "&bcsv=", item->bms_status.bcs_test_voltage);
	set_cmd_float(buf, "&bcsa=", item->bms_status.bcs_test_current);
	set_cmd_float(buf, "&bcsdv=", item->bms_status.bcs_max_single_voltage);
	set_cmd_value(buf, "&bcsn=", item->bms_status.bcs_max_single_no);
	set_cmd_value(buf, "&bcssoc=", item->bms_status.bcs_current_soc);

}

//账单信息
static void gtc_pack_bill_msg(struct GtcBillInfo *bill, char_t *buf) {
    set_cmd_str(buf, "cmd=", "cmsg");
    set_cmd_str(buf, "&sno=", gtc_params.dev_id);
    char_t gunnum_str[32];
    memset(gunnum_str, 0, sizeof(gunnum_str));
	  get_gunnum_str(bill->gun_id, gunnum_str);
    set_cmd_str(buf, "&subid=", gunnum_str);
    set_cmd_str(buf, "&userid=", bill->user_id);
    set_cmd_str(buf, "&dno=", bill->order_id);
    set_cmd_value(buf, "&socb=", bill->start_soc);
    set_cmd_value(buf, "&soce=", bill->end_soc);
    set_cmd_str(buf, "&ctype=", get_charge_type_str(bill->charge_type));
    set_cmd_float(buf, "&tval=", bill->charge_type_value);
    set_cmd_str(buf, "&end=", bill->err_no);
    set_cmd_float(buf, "&bkwh=", bill->start_charge_kwh_meter);
    set_cmd_float(buf, "&ekwh=", bill->end_charge_kwh_meter);
    set_cmd_value(buf, "&btime=", bill->charge_start_time);
    set_cmd_value(buf, "&bend=", bill->charge_end_time);
    set_cmd_float(buf, "&tkwh=", bill->end_charge_kwh_meter - bill->start_charge_kwh_meter);
    set_cmd_value(buf, "&ttime=", bill->charge_end_time - bill->charge_start_time);
    set_cmd_str(buf, "&costtype=", "tzone"); 
    char_t kwh_zone_str[200]={0};
    get_kwh_zone_str(bill->kwh_amount, kwh_zone_str);
    set_cmd_str(buf, "&tzone=",kwh_zone_str);
}

//刷卡鉴权报文
static void gtc_pack_card_auth_msg(uint32_t gunnum, char_t *id, char_t *pwd, uint8_t type, uint32_t value, char_t *buf) {
    char_t gunnum_str[32]={0};
    get_gunnum_str(gtc_client.item[gunnum-1].gun_status.gun_id, gunnum_str);
        
    set_cmd_str(buf, "cmd=", "cardauth");
    set_cmd_str(buf, "&sno=", gtc_params.dev_id);
    set_cmd_str(buf, "&subid=", gunnum_str);
    set_cmd_str(buf, "&cardid=", id);
    set_cmd_str(buf, "&pwd=", pwd);
    set_cmd_value(buf, "&ctype=", type);
    set_cmd_float(buf, "&tval=", value);
}

static void gtc_pack_start_charge_ack(struct GtcClientItem *item, char_t *ret, char_t *buf) {
    char_t gunnum_str[32]={0};
    get_gunnum_str(item->gun_status.gun_id, gunnum_str);

    set_cmd_str(buf, "cmd=", "open");
    set_cmd_str(buf, "&sno=", gtc_params.dev_id);
    set_cmd_str(buf, "&subid=", gunnum_str);
    set_cmd_str(buf, "&userid=", item->gun_status.charge_user_id);
    set_cmd_str(buf, "&dno=", item->gun_status.order_id);
    set_cmd_value(buf, "&ctype=", item->gun_status.charge_type);
    set_cmd_float(buf, "&tval=", item->gun_status.charge_type_value);
    set_cmd_str(buf, "&ret=", ret);
}

static void gtc_pack_stop_charge_ack(struct GtcClientItem *item, char_t *ret, char_t *buf) {
    char_t gunnum_str[32]={0};
    get_gunnum_str(item->gun_status.gun_id, gunnum_str);

    set_cmd_str(buf, "cmd=", "close");
    set_cmd_str(buf, "&sno=", gtc_params.dev_id);
    set_cmd_str(buf, "&subid=", gunnum_str);
    set_cmd_str(buf, "&userid=", item->gun_status.charge_user_id);
    set_cmd_str(buf, "&dno=", item->gun_status.order_id);
    set_cmd_str(buf, "&ret=", ret);
    set_cmd_str(buf, "&msg=", ret);
}

static void gtc_pack_update_get_file_cmd(const struct T_updateInfo *info, char_t *buf) {
    set_cmd_str(buf, "cmd=", "update");
    set_cmd_str(buf, "&subcmd=", "fileget");
    set_cmd_str(buf, "&sno=", info->sno);
    set_cmd_str(buf, "&sver=", info->ver);
    set_cmd_str(buf, "&name=", info->name);
    set_cmd_value(buf, "&num=", info->num);
    set_cmd_value(buf, "&len=", info->packetLen);
}

static void gtc_pack_update_state_ack(const struct T_updateInfo *info, const char *ret, char_t *buf) {
    set_cmd_str(buf, "cmd=", "update");
    set_cmd_str(buf, "&subcmd=", "ack");
    set_cmd_str(buf, "&sno=", info->sno);
    set_cmd_str(buf, "&sver=", info->ver);
    set_cmd_str(buf, "&name=", info->name);
    set_cmd_value(buf, "&tlen=", info->totalLen);
    set_cmd_str(buf, "&ret=", ret);
}


int32_t count_letter_num_len(const char_t *data)
{
    int32_t len = 0;
    if(NULL != data) {
        while(1) {
            if( ('0' <= *(data+len) && '9' >= *(data+len)) 
            || ('a' <= *(data+len) && 'z' >= *(data+len))
            || ('A' <= *(data+len) && 'Z' >= *(data+len))) {
                len++;
            }
            else {
                break;
            }
        }
        return len;
    }
    return -1;
}


char_t check_cpu(void)
{
    char_t mode = GTC_BIG_MODE;
    int32_t a = 1;
    char_t *p = (char_t *)&a;
    if(*p == (char_t)1)
    {
        mode = GTC_LITTLE_MODE;
    }
    return mode;
}


static void gtc_add_cmd_handle(struct GtcCmdInfo* info,enum GtcCmdType cmd,uint8_t* data,uint16_t len)
{
    uint8_t point_to_end = 0;
    
    if(info->sum < MAX_GTC_INCIDENT_SUM && ((NULL != data && len <= MAX_GTC_INCIDENT_DATA_LEN) || (NULL == data && 0 == len)))
    {
        point_to_end = info->cmd_new + info->sum;
        point_to_end = (point_to_end >= MAX_GTC_INCIDENT_SUM) ? ( point_to_end -= MAX_GTC_INCIDENT_SUM) : (point_to_end);
        info->list[point_to_end].cmd = cmd;
        if(NULL != data)
        {
            memcpy(&info->list[point_to_end].data[0],data,len);
            info->list[point_to_end].len = len;
        }      
        info->sum++;     
    }else{
		printf("gtc_add_cmd_handle add err\r\n");
	}
}

#if 0 //接收处理部分

#endif

static void cmd_sign_in_ack(char_t *dataStr) {
    
    char msgBuf[32] = {0};
    char time[32] = {0};

    get_cmd_str(dataStr, "msg",  msgBuf);
    get_cmd_str(dataStr, "time",  time);

    if (str_equal(msgBuf, "succ"))
    {
        uint64_t timel = (uint64_t)strtoll(time, NULL, 10);
        gtc_client.recv_protocol.sign_in_ack.time = (uint32_t)(timel / 1000); //转成秒数
        gtc_client.recv_protocol.recv_sign_in_ack_flag = ECO_TRUE;
    }
}

static uint8_t get_subid_num(char_t *str){
	char_t num[3] = {0};
    
	num[1]=str[strlen(str)-1];
	num[0]=str[strlen(str)-2];
	return (uint8_t)strtol(num, NULL, 10);
}

static void cmd_card_auth_ack(char_t *str){
    struct GtcSwipCardAck msg = {0};
    char_t subid[GTC_MAX_CHAEGE_USER_ID_LEN+1]={0}; 
    get_cmd_str(str, "subid", subid);
    msg.gunid = get_subid_num(subid);
    get_cmd_str(str, "cardid", msg.card_id);
    get_cmd_str(str, "userid", msg.user_id);
    get_cmd_str(str, "devowner", msg.dev_owner);
    get_cmd_str(str, "cardowner", msg.card_owner);
    char_t ret[16]={0};    
    get_cmd_str(str, "ret", ret);
    msg.ret = get_card_auth_ack_ret(ret);  
    if (strncmp(msg.dev_owner, msg.card_owner, sizeof(msg.dev_owner)) != 0){
        msg.ret = (uint8_t)CARD_AUTH_INVALID_USER;  
    }
    get_cmd_str(str, "dno", msg.dno);

    char_t type[10]={0};
    get_cmd_str(str, "type", type);
    msg.type = get_charge_type_num(type);
    msg.value = get_cmd_float(str, "value");
    
    gtc_add_cmd_handle(&gtc_client.cmd_info, gtc_cmd_type_swip_card_ack, (uint8_t *)&msg, sizeof(msg));
}
   

static void cmd_server_start(char_t *str){
	struct GtcServerStartMsg msg = {0};    
	char_t subid[GTC_MAX_CHAEGE_USER_ID_LEN+1]={0}; 

    get_cmd_str(str, "subid", subid);
    msg.gunid = get_subid_num(subid);
	get_cmd_str(str, "userid", msg.userId);
	get_cmd_str(str, "dno", msg.dno);
	char_t type[10];
	get_cmd_str(str, "type", type);
	msg.type = get_charge_type_num(type);
	msg.value = get_cmd_value(str, "value");

	gtc_add_cmd_handle(&gtc_client.cmd_info, gtc_cmd_type_start_charge, (uint8_t *)&msg, sizeof(msg));
}

static void cmd_settle_ack(char_t *str){
    struct GtcSettleAckMsg msg = {0};
    char_t subid[GTC_MAX_CHAEGE_USER_ID_LEN+1]={0};
    
    get_cmd_str(str, "subid", subid);
    msg.gunid = get_subid_num(subid);
	get_cmd_str(str, "userid", msg.userId);
	get_cmd_str(str, "dno", msg.dno);

    msg.charge_sec = get_cmd_value(str, "ctime");
    msg.charge_ah = get_cmd_float(str, "cah");
    msg.charge_kwh = get_cmd_float(str, "ckwh");

    msg.elec_cost = get_cmd_float(str, "costele");
    msg.serv_cost = get_cmd_float(str, "costser");
    msg.total_cost = get_cmd_float(str, "costtotal");  

    memcpy(&gtc_client.recv_protocol.settle_ack, &msg, sizeof(gtc_client.recv_protocol.settle_ack));
    gtc_client.recv_protocol.settle_ack_flag = ECO_TRUE;
    
    //gtc_add_cmd_handle(&gtc_client.cmd_info, gtc_cmd_type_settle_ack, (uint8_t *)&msg, sizeof(msg));
}

static void cmd_server_stop(char_t *str){
    struct GtcServerStopMsg msg={0};
	char_t subid[GTC_MAX_CHAEGE_USER_ID_LEN+1]={0};
    
    get_cmd_str(str, "subid", subid);
    msg.gunid = get_subid_num(subid);
    get_cmd_str(str, "userid", msg.userId);
    get_cmd_str(str, "dno", msg.dno);

    gtc_add_cmd_handle(&gtc_client.cmd_info, gtc_cmd_type_stop_charge, (uint8_t *)&msg, sizeof(msg));
}

static void cmd_cost_mode_set(char_t *str){
    struct GtcCostModeMsg msg={0};
    char type[16]={0};
    get_cmd_str(str, "type", type);

    if (strncmp(type, "single", 6) == 0){
        uint16_t elec_cost = get_cmd_value(str, "eleccost"); //平台传下来的数据已经*100了
        uint16_t serv_cost = get_cmd_value(str, "servcost");
        for(uint32_t i=0;i< 48;i++){
            msg.fee.charge_fee[i] = elec_cost;
            msg.fee.service_fee[i] = serv_cost;
        }
        
        gtc_add_cmd_handle(&gtc_client.cmd_info, gtc_cmd_type_params_updated, (uint8_t *)&msg, sizeof(msg));
        
    }else if (strncmp(type, "tzone", 5) == 0){
        char_t fee[500]={0};
        get_cmd_str(str, "tzone", fee);
        if (get_cmd_cost(fee, msg.fee.charge_fee, msg.fee.service_fee, 48) != 0){
            return;
        }
        
        gtc_add_cmd_handle(&gtc_client.cmd_info, gtc_cmd_type_params_updated, (uint8_t *)&msg, sizeof(msg));
        
    }else{
        log(LOG_WARNING, "cost mode:%s err\r\n", type);
    }
}

static void cmd_para_set(char_t *str) {
    char val[16]={0};
    get_cmd_str(str, "reboot", val);
    if (strncmp(val, "yes", 3)==0){
        callback_reboot_system();
    }
}

static void UpdateCmdRec(char_t *str) {
    struct GtcUpdateCmdRecMsg msg = {0};

    get_cmd_str( str, "sno", msg.sno);
    get_cmd_str( str, "sver", msg.sver);
    get_cmd_str(str, "name", msg.name);
    msg.tlen = get_cmd_value(str, "tlen");
    get_cmd_str( str, "time", msg.time);

    printf("tlen = %d\r\n", (int)msg.tlen);

    if (strlen(msg.sver) > 16 || strlen(msg.name) > 16) {
        return;
    }
    
    gtc_add_cmd_handle(&gtc_client.cmd_info, gtc_cmd_type_software_upgrade_cmd, (uint8_t *)&msg, sizeof(msg));
}

static void UpdateFileRec(char_t *str) {
    struct T_UpdateFileRecMsg msg = {0};
    get_cmd_str(str, "sno",  msg.sno);
    get_cmd_str(str, "sver", msg.sver);
    get_cmd_str(str, "name", msg.name);
    msg.num = get_cmd_value(str, "num");

    get_cmd_str(str, "data", gtc_recv_file_buf);
    msg.crc = get_cmd_value(str, "crc");
    msg.len = get_cmd_value(str, "len");

    gtc_add_cmd_handle(&gtc_client.cmd_info, gtc_cmd_type_software_upgrade_file, (uint8_t *)&msg, sizeof(msg));
}

static void cmd_update(char_t *str) {
    char subCmd[32] = {0};
    get_cmd_str(str, "subcmd", subCmd);
    if (str_equal(subCmd, "dev")) {
        UpdateCmdRec(str);
    } else if (str_equal(subCmd, "fileack")) {
        UpdateFileRec(str);
    }
}

void mqtt_deal_msg(char_t *str) {
    char_t cmd[32] = {0};
    get_cmd_str(str, "cmd", cmd);
    if (str_equal(cmd, "init")){ /*签到报文应答*/
        cmd_sign_in_ack(str);
    }else if (str_equal(cmd, "cardauth")){ /*刷卡认证报文应答*/
        cmd_card_auth_ack(str);
    }else if (str_equal(cmd, "open")){ /*开启充电*/
    	cmd_server_start(str);
    }else if (str_equal(cmd, "cmsg")) { /*结算应答报文*/
        cmd_settle_ack(str);
    }else if (str_equal(cmd, "close")) { /*结束充电*/
        cmd_server_stop(str);
    }else if (str_equal(cmd, "costmode")) { /*计费模型*/
        cmd_cost_mode_set(str);
    }else if (str_equal(cmd, "paraset")) { /*参数设置*/
        cmd_para_set(str);
    }else if (str_equal(cmd, "update")) { /*远程升级*/
        cmd_update(str);
    }else if (str_equal(cmd, "reserve")) { /*预约*/
    
    }else{
        
    }
}

static void cmd_start_charge_ack(uint8_t gunid, char_t *ret){
    char_t buf[MQTT_SENT_QUEUE_ITEM_LEN+1];
    memset(buf, 0, sizeof(buf));
    gtc_pack_start_charge_ack(&gtc_client.item[gunid-1], ret, buf);
    gtc_mqtt_send_cmd(gtc_cmd_start_charge_ack, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);
}

static void cmd_stop_charge_ack(uint8_t gunid, char_t *ret){
    char_t buf[MQTT_SENT_QUEUE_ITEM_LEN+1];
    memset(buf, 0, sizeof(buf));
    gtc_pack_stop_charge_ack(&gtc_client.item[gunid-1], ret, buf);
    gtc_mqtt_send_cmd(gtc_cmd_stop_charge_ack, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);
}

static void sync_gun_status(struct GtcClientItem *item ,struct ClientUserGunInfo *user_gun_status ,uint16_t gun_cnt ) {
	uint8_t i = 0;

    assert(item != NULL);
    assert(user_gun_status != NULL);
    assert(gun_cnt != 0);

    for(i = 0 ;i < gun_cnt ;i++)
    {
        item[i].gun_status.car_connection_stat = (enum GtcCarConnectState)user_gun_status[i].car_connection_stat;
        item[i].gun_status.soc_percent = user_gun_status[i].soc_percent;
        item[i].gun_status.dc_charge_voltage = user_gun_status[i].dc_charge_voltage;
        item[i].gun_status.dc_charge_current = user_gun_status[i].dc_charge_current;
        item[i].gun_status.bms_need_voltage = user_gun_status[i].bms_need_voltage;
        item[i].gun_status.bms_need_current = user_gun_status[i].bms_need_current;
        item[i].gun_status.ac_a_vol = user_gun_status[i].ac_a_vol;
        item[i].gun_status.ac_b_vol = user_gun_status[i].ac_b_vol;
        item[i].gun_status.ac_c_vol = user_gun_status[i].ac_c_vol;
        item[i].gun_status.ac_a_cur = user_gun_status[i].ac_a_cur;
        item[i].gun_status.ac_b_cur = user_gun_status[i].ac_b_cur;
        item[i].gun_status.ac_c_cur = user_gun_status[i].ac_c_cur;
        item[i].gun_status.current_meter_kwh_num = user_gun_status[i].meter_kwh_num;
        item[i].gun_status.charge_power_kw = user_gun_status[i].charge_power_kw;
        item[i].gun_status.left_time =  user_gun_status[i].left_time;
    }
}

static void sync_bms_status(struct GtcClientItem *item, struct ClientUserBmsInfo* user_bms_status ,uint16_t gun_cnt ) {
	int i = 0;
    
	assert(item != NULL);
    assert(user_bms_status != NULL);
    assert(gun_cnt != 0);

    for(i = 0 ;i < gun_cnt ;i++ )
    {
        memcpy(item[i].bms_status.brm_bms_connect_version, user_bms_status[i].brm_bms_connect_version,GTC_MAX_BRM_BMS_CONNECT_VERSION_LEN);
        item[i].bms_status.brm_battery_type = (enum GtcBatteryType)user_bms_status[i].brm_battery_type;
        item[i].bms_status.brm_battery_power = user_bms_status[i].brm_battery_power;
        item[i].bms_status.brm_battery_volt = user_bms_status[i].brm_battery_volt;
        item[i].bms_status.brm_battery_supplier = user_bms_status[i].brm_battery_supplier;
        item[i].bms_status.brm_battery_seq = user_bms_status[i].brm_battery_seq;
        item[i].bms_status.brm_battery_produce_year = user_bms_status[i].brm_battery_produce_year;
        item[i].bms_status.brm_battery_produce_month = user_bms_status[i].brm_battery_produce_month;
        item[i].bms_status.brm_battery_produce_day = user_bms_status[i].brm_battery_produce_day;
        item[i].bms_status.brm_battery_charge_count = user_bms_status[i].brm_battery_charge_count;
        item[i].bms_status.brm_battery_property_identification = user_bms_status[i].brm_battery_property_identification;
        memcpy(item[i].bms_status.brm_vin, user_bms_status[i].brm_vin,GTC_MAX_BRM_VIN_LEN);
        memcpy(item[i].bms_status.brm_bms_software_version, user_bms_status[i].brm_bms_software_version,GTC_MAX_BRM_BMS_SOFTWARE_VERSION_LEN);
        item[i].bms_status.bcp_max_voltage = user_bms_status[i].bcp_max_voltage;
        item[i].bms_status.bcp_max_current = user_bms_status[i].bcp_max_current;
        item[i].bms_status.bcp_max_power = user_bms_status[i].bcp_max_power;
        item[i].bms_status.bcp_total_voltage = user_bms_status[i].bcp_total_voltage;
        item[i].bms_status.bcp_max_temperature = user_bms_status[i].bcp_max_temperature;
        item[i].bms_status.bcp_battery_soc = user_bms_status[i].bcp_battery_soc;
        item[i].bms_status.bcp_battery_soc_current_voltage = user_bms_status[i].bcp_battery_soc_current_voltage;
        item[i].bms_status.bro_bms_is_ready = user_bms_status[i].bro_bms_is_ready;
        item[i].bms_status.bcl_voltage_need = user_bms_status[i].bcl_voltage_need;
        item[i].bms_status.bcl_current_need = user_bms_status[i].bcl_current_need;
        item[i].bms_status.bcl_charge_mode = user_bms_status[i].bcl_charge_mode;
        item[i].bms_status.bcs_test_voltage = user_bms_status[i].bcs_test_voltage;
        item[i].bms_status.bcs_test_current = user_bms_status[i].bcs_test_current;
        item[i].bms_status.bcs_max_single_voltage = user_bms_status[i].bcs_max_single_voltage;
        item[i].bms_status.bcs_max_single_no = user_bms_status[i].bcs_max_single_no;
        item[i].bms_status.bcs_current_soc = user_bms_status[i].bcs_current_soc;
        item[i].bms_status.charge_time_left = user_bms_status[i].charge_time_left;
        item[i].bms_status.bsm_single_no = user_bms_status[i].bsm_single_no;
        item[i].bms_status.bsm_max_temperature = user_bms_status[i].bsm_max_temperature;
        item[i].bms_status.bsm_max_temperature_check_no = user_bms_status[i].bsm_max_temperature_check_no;
        item[i].bms_status.bsm_min_temperature = user_bms_status[i].bsm_min_temperature;
        item[i].bms_status.bsm_min_temperature_check_no = user_bms_status[i].bsm_min_temperature_check_no;
        item[i].bms_status.bsm_voltage_too_high_or_too_low = user_bms_status[i].bsm_voltage_too_high_or_too_low;
        item[i].bms_status.bsm_car_battery_soc_too_high_or_too_low = user_bms_status[i].bsm_car_battery_soc_too_high_or_too_low;
        item[i].bms_status.bsm_car_battery_charge_over_current = user_bms_status[i].bsm_car_battery_charge_over_current;
        item[i].bms_status.bsm_battery_temperature_too_high = user_bms_status[i].bsm_battery_temperature_too_high;
        item[i].bms_status.bsm_battery_insulation_state = user_bms_status[i].bsm_battery_insulation_state;
        item[i].bms_status.bsm_battery_connect_state = user_bms_status[i].bsm_battery_connect_state;
        item[i].bms_status.bsm_allow_charge = user_bms_status[i].bsm_allow_charge;
        item[i].bms_status.bst_bms_soc_target = user_bms_status[i].bst_bms_soc_target;
        item[i].bms_status.bst_bms_voltage_target = user_bms_status[i].bst_bms_voltage_target;
        item[i].bms_status.bst_single_voltage_target = user_bms_status[i].bst_single_voltage_target;
        item[i].bms_status.bst_finish = user_bms_status[i].bst_finish;
        item[i].bms_status.bst_isolation_error = user_bms_status[i].bst_isolation_error;
        item[i].bms_status.bst_connect_over_temperature = user_bms_status[i].bst_connect_over_temperature;
        item[i].bms_status.bst_over_temperature = user_bms_status[i].bst_over_temperature;
        item[i].bms_status.bst_connect_error = user_bms_status[i].bst_connect_error;
        item[i].bms_status.bst_battery_over_temperature = user_bms_status[i].bst_battery_over_temperature;
        item[i].bms_status.bst_high_voltage_relay_error = user_bms_status[i].bst_high_voltage_relay_error;
        item[i].bms_status.bst_point2_test_error = user_bms_status[i].bst_point2_test_error;
        item[i].bms_status.bst_other_error = user_bms_status[i].bst_other_error;
        item[i].bms_status.bst_current_too_high = user_bms_status[i].bst_current_too_high;
        item[i].bms_status.bst_voltage_too_high = user_bms_status[i].bst_voltage_too_high;
        item[i].bms_status.bst_stop_soc = user_bms_status[i].bst_stop_soc;
        item[i].bms_status.bsd_battery_low_voltage = user_bms_status[i].bsd_battery_low_voltage;
        item[i].bms_status.bsd_battery_high_voltage = user_bms_status[i].bsd_battery_high_voltage;
        item[i].bms_status.bsd_battery_low_temperature = user_bms_status[i].bsd_battery_low_temperature;
        item[i].bms_status.bsd_battery_high_temperature = user_bms_status[i].bsd_battery_high_temperature;
        item[i].bms_status.bem_error_spn2560_00 = user_bms_status[i].bem_error_spn2560_00;
        item[i].bms_status.bem_error_spn2560_aa = user_bms_status[i].bem_error_spn2560_aa;
        item[i].bms_status.bem_error_time_sync = user_bms_status[i].bem_error_time_sync;
        item[i].bms_status.bem_error_ready_to_charge = user_bms_status[i].bem_error_ready_to_charge;
        item[i].bms_status.bem_error_receive_status = user_bms_status[i].bem_error_receive_status;
        item[i].bms_status.bem_error_receive_stop_charge = user_bms_status[i].bem_error_receive_stop_charge;
        item[i].bms_status.bem_error_receive_report = user_bms_status[i].bem_error_receive_report;
        item[i].bms_status.bem_error_other = user_bms_status[i].bem_error_other;
    }	
 }

static void reconnection_handle(struct GtcParams *param) 
{

}

static void gtc_set_gun_qr(uint8_t gun_cnt, uint8_t*qr_str, uint16_t len)
{

}

static void gtc_start_charge(const struct GtcServerStartMsg* msg) {   

    char_t err[GTC_MAX_ERR_NO_LEN+1];
    uint8_t gun_index = 0;
    memset(err, 0, sizeof(err));

	gun_index = msg->gunid - 1;
	
    if(gun_index < gtc_params.gun_cnt)	{
        callback_start_charge(msg->gunid, err);

		struct GtcGunStatus *gun = &gtc_client.item[gun_index].gun_status;
    	gun->charge_type = msg->type;
		gun->charge_type_value = msg->value;
        strncpy(gun->order_id, msg->dno, sizeof(gun->order_id));
		strncpy(gun->charge_user_id,msg->userId, sizeof(gun->charge_user_id));
		
        if(4 == count_letter_num_len(err) && 0 == strncmp(err, "0000", 4)) {
            strncpy(gun->alarm_code, err, sizeof(gun->alarm_code));
            gun->work_stat = gtc_work_stat_charging;
        }
        else {
            //strncpy(gun->alarm_code, err, sizeof(gun->alarm_code));
            //gun->work_stat = gtc_work_stat_in_error;
        }	
	}
    else {	
        printf("gtc_start_charge gun_index:%d err\r\n", gun_index);
	    strncpy(err,"2002",4); 
	}

    cmd_start_charge_ack(msg->gunid, err);
   
}

static void gtc_stop_charge(const struct GtcServerStopMsg *msg){
    char err[GTC_MAX_ERR_NO_LEN+1];
    uint8_t gun_index = 0;
    
    memset(err, 0,sizeof(err));
    gun_index = msg->gunid - 1;
    
    if(gun_index < gtc_params.gun_cnt  
        && gtc_work_stat_charging == gtc_client.item[gun_index].gun_status.work_stat
        && 0 == strncmp(gtc_client.item[gun_index].gun_status.order_id, msg->dno, GTC_MAX_CHAEGE_USER_ID_LEN)) {
      
        callback_stop_charge(msg->gunid,err);
        gtc_send_touch_charge_stoped(msg->gunid, "1001");//APP停止

        cmd_stop_charge_ack(msg->gunid, "1001");

	}
}

static void gtc_cost_set(const struct GtcCostModeMsg *msg){
    memcpy(&gtc_params.fee_config, &msg->fee, sizeof(gtc_params.fee_config));
}

static void gtc_card_auth_ack(const struct GtcSwipCardAck *msg){
    char_t err[GTC_MAX_ERR_NO_LEN+1];
    uint8_t gun_index = 0;
    memset(err, 0, sizeof(err));

	gun_index = msg->gunid - 1;

    if (msg->ret != CARD_AUTH_SUCC){
        callback_card_ack(msg->gunid, msg->ret);
        return;
    }
	
    if(gun_index < gtc_params.gun_cnt)	{
        callback_start_charge(msg->gunid, err);

		struct GtcGunStatus *gun = &gtc_client.item[gun_index].gun_status;
    	gun->charge_type = msg->type;
		gun->charge_type_value = msg->value;
        strncpy(gun->order_id, msg->dno, sizeof(gun->order_id));
		strncpy(gun->charge_user_id,msg->user_id, sizeof(gun->charge_user_id));
		
        if(4 == count_letter_num_len(err) && 0 == strncmp(err, "0000", 4)) {
            strncpy(gun->alarm_code, err, sizeof(gun->alarm_code));
            gun->work_stat = gtc_work_stat_charging;
        }
        else {
            //strncpy(gun->alarm_code, err, sizeof(gun->alarm_code));
            //gun->work_stat = gtc_work_stat_in_error;
        }	
	}
    else {	
        printf("gtc_start_charge gun_index:%d err\r\n", gun_index);
	    strncpy(err,"2002",4); 
	}

    cmd_start_charge_ack(msg->gunid, err);    
}

static void gtc_del_recently_incident_handle(struct GtcCmdInfo* info) {
    uint8_t point_to_head = info->cmd_new;
    
    if(info->cmd_new < MAX_GTC_INCIDENT_SUM && info->sum >= 1) {
        info->list[info->cmd_new].cmd = gtc_cmd_type_null;
        memset(&info->list[info->cmd_new].data[0], 0, sizeof(info->list[info->cmd_new].data[0]));
        info->list[info->cmd_new].len = 0;
        info->sum--;
        if(info->sum > 0) {
            point_to_head++;
            if (point_to_head >= MAX_GTC_INCIDENT_SUM){
                point_to_head = 0;
            }
            info->cmd_new = point_to_head;
        }  
    }
}

static void gtc_recv_update_cmd(struct T_UpdateCmdRecMsg *msg){
    char_t buf[500]={0};
    struct T_updateInfo *up = &gtc_updateInfo;
    
    strcpy(up->sno, msg->sno);
    strcpy(up->ver, msg->sver);
    strcpy(up->name, msg->name);
    up->num = 1;
    up->totalLen = msg->tlen;
    up->packetLen = 500;  //每个包大小，为固定值
    up->status = (uint8_t)UPDATE_LOADING;
    up->cnt = 0;
    up->recvLen = 0;
    printf("ver = %s\r\n", up->ver);
    printf("name = %s\r\n", up->name);
    printf("totallen = %d\r\n", (int32_t)up->totalLen);

    callback_save_update_file((uint8_t *)up, sizeof(struct T_updateInfo));
    
    gtc_pack_update_get_file_cmd(&gtc_updateInfo, buf);
    gtc_mqtt_send_cmd(gtc_cmd_update_cmd_ack, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);
}

static void GtcUpdate_UpdateSendGetFileCmd(struct T_updateInfo *up){
    char_t send_buf[500]={0};
    gtc_pack_update_get_file_cmd(up, send_buf);
    gtc_mqtt_send_cmd(gtc_cmd_update_cmd_ack, send_buf, strlen(send_buf), gtc_params.network_cmd_timeout, QOS_1);
}

static void GtcProtIntf_UpdateSendAck(struct T_updateInfo *up, char_t *ret){
    char_t send_buf[500]={0};
    
    gtc_pack_update_state_ack(up, ret, send_buf);
    gtc_mqtt_send_cmd(gtc_cmd_update_cmd_ack, send_buf, strlen(send_buf), gtc_params.network_cmd_timeout, QOS_1);
}

void GtcUpdate_RemoteGetFile(struct T_updateInfo *up, const struct T_UpdateFileRecMsg *updateData) {

    char_t *data = gtc_recv_file_buf;
    up->cnt = 0;
    char_t buf[512] = {0};
    if (up->num != updateData->num) {
        if (up->recvLen < up->totalLen) {
            GtcUpdate_UpdateSendGetFileCmd(up);
        }
        return;
    }
    
    uint32_t len = updateData->len;
    ASC_to_BCD((uint8_t *)buf, (uint8_t *)data, len*2);

    uint16_t crc = Crc16(0xffff, (uint8_t *)buf, len);

    if (crc != updateData->crc) {
        printf("crc fail crc:%02x reccrc:%02x len:%d\r\n", crc, updateData->crc, (int32_t)len);
        if (up->recvLen < up->totalLen) {
            GtcUpdate_UpdateSendGetFileCmd(up);
        }
        return;
    }
    int32_t pos = (int32_t)up->recvLen;

    if (callback_push_update_file_data(up->name, pos, buf, (int32_t)len) != 0) {
        printf("GtcData_PushUpdateFileData fail pos = %d\r\n", pos);
        if (up->recvLen < up->totalLen) {
            GtcUpdate_UpdateSendGetFileCmd(up);
        }
        return;
    }
    
    up->num++;
    up->recvLen += len;
    printf("update %d/100\r", (int32_t)(up->recvLen*100/up->totalLen));
    
    if (up->recvLen < up->totalLen) { //说明整数包已经发完了
        GtcUpdate_UpdateSendGetFileCmd(up);
    } else {
        up->status = (uint8_t)UPDATE_LOADED;
        GtcProtIntf_UpdateSendAck(up, "succ");
    }

    callback_save_update_file((uint8_t *)up, sizeof(struct T_updateInfo));

    if (up->status == (uint8_t)UPDATE_LOADED) {
        printf("updata success reboot sys\r\n");
        callback_reboot_system();
    }

}

static void gtc_recv_update_file(struct T_UpdateFileRecMsg *msg){
    GtcUpdate_RemoteGetFile(&gtc_updateInfo, msg);
}

void gtc_cmd_info_handle(struct GtcCmdInfo *info)
{
    uint8_t *param = info->list[info->cmd_new].data;
    uint16_t param_len = info->list[info->cmd_new].len;
    
    if(info->sum > 0)
    {
        switch(info->list[info->cmd_new].cmd)
        {
            case gtc_cmd_type_reconnection:
            {
                reconnection_handle(&gtc_params);
                break;
            }
            case gtc_cmd_type_set_left_qr://code 3 cmd 17
            {
                gtc_set_gun_qr(0,param,param_len);
                break;
            }
            case gtc_cmd_type_set_righ_qr://code 3 cmd 19
            {
                gtc_set_gun_qr(1,param,param_len);
                break;
            }
            case gtc_cmd_type_start_charge:
            {
                gtc_start_charge((struct GtcServerStartMsg*)param);			
                break;
            }
            case gtc_cmd_type_stop_charge:
            {
                gtc_stop_charge((struct GtcServerStopMsg *)param);
                break;
            }
            case gtc_cmd_type_set_time:
            {
                //xj_set_sys_time((xj_sync_system_time_param*)param);
                break;
            }
            case gtc_cmd_type_software_upgrade_cmd:
            {
                gtc_recv_update_cmd((struct T_UpdateCmdRecMsg*)param);
                //xj_software_download((xj_software_upgrade_param*)param);
                break;
            }
            case gtc_cmd_type_software_upgrade_file:
                gtc_recv_update_file((struct T_UpdateFileRecMsg *)param);
            break;
            case gtc_cmd_type_params_updated:
            {
                gtc_cost_set((struct GtcCostModeMsg *)param);
                break;
            }
            case gtc_cmd_type_upload_log:
            {
                //xj_upload_log((xj_upload_log_param*)param);
                break;
            }
            case gtc_cmd_type_control_cmd:
            {
                //xj_code5_control_handle((xj_control_cmd_param*)param);
                break;
            }
            case gtc_cmd_type_swip_card_ack:
                gtc_card_auth_ack((struct GtcSwipCardAck *)param);
            break;
            default:
            {
                break;
            }
        }

        gtc_del_recently_incident_handle(info);
    }
}

#if 0 //发送部分

#endif

static int32_t send_msg_to_queue(uint8_t qos, void *cmd, int32_t len){
    struct MqttSendMsg msg;
    memset(&msg, 0, sizeof(msg));
    msg.qos = qos;
    memcpy(msg.data, cmd, len);
    return mqtt_send_msg(&msg);
}

void gtc_wait_cmd_ack(uint8_t *flag, uint16_t time_out){
    uint16_t i=0;
    while((i < time_out * 100) && (*flag == ECO_FALSE))
    {
        os_msleep(10U);
        i++;
    } 
}

static void *gtc_mqtt_send_cmd(enum GtcMqttCmdType cmd_type, void * cmd, int32_t len, uint16_t time_out, uint8_t qos) {
    void* param_ret = NULL;
    
    assert(cmd != NULL);

    /*未连接时，允许签到报文发送*/
	if((gtc_client.is_login == LOGIN_FALSE) && (cmd_type != gtc_cmd_sign_in)){
		return NULL;
    }
	
	switch (cmd_type) {   
	    case gtc_cmd_sign_in:
		{
            gtc_client.recv_protocol.recv_sign_in_ack_flag = ECO_FALSE;
            send_msg_to_queue(qos, cmd, len);
            gtc_wait_cmd_ack(&gtc_client.recv_protocol.recv_sign_in_ack_flag, time_out);
			if(gtc_client.recv_protocol.recv_sign_in_ack_flag == ECO_TRUE)
			{
				param_ret = &gtc_client.recv_protocol.sign_in_ack;
			}            
			break;
		}
        case gtc_cmd_status:
            send_msg_to_queue(qos, cmd, len);
        break;
        case gtc_cmd_bms:
            send_msg_to_queue(qos, cmd, len);
        break;
        case gtc_cmd_card_auth:
            send_msg_to_queue(qos, cmd, len);
        break;
        case gtc_cmd_start_charge_ack:
            send_msg_to_queue(qos, cmd, len);
        break;
        case gtc_cmd_stop_charge_ack:
            send_msg_to_queue(qos, cmd, len);
        break;

        case gtc_cmd_bill_charging:
            gtc_client.recv_protocol.settle_ack_flag = ECO_FALSE;
            send_msg_to_queue(qos, cmd,len);
            gtc_wait_cmd_ack(&gtc_client.recv_protocol.settle_ack_flag, time_out);
            if (gtc_client.recv_protocol.settle_ack_flag == ECO_TRUE){
                param_ret = &gtc_client.recv_protocol.settle_ack;
            }            
        break;
        case gtc_cmd_update_cmd_ack:
            send_msg_to_queue(qos, cmd, len);
        break;
		default:
		{	
			break;
		}
	}
	  
	return param_ret;
}

struct GtcMqttRespItem *gtc_poll_mqtt_resp_to_send(void)
{
	int i=0;
	for(i=0; i<MAX_BLOCKED_MQTT_RESP_NUM; i++)
	{
		if(gtc_client.resp_queue[i].submited == 1)
		{
			return &(gtc_client.resp_queue[i]);
		}
	}
	return NULL;
}

void gtc_interval_work_for_send_mqtt_resp(void)
{
	struct GtcMqttRespItem *resp = gtc_poll_mqtt_resp_to_send();//根据响应标志位，判断是否有消息需要去回复
	if(NULL != resp)
	{
		gtc_mqtt_send_resp(resp->cmd_type,resp->data,resp->qos);
		resp->submited = 0;
	}	
}

void gtc_interval_work_for_sign_in(void) {
    char_t buf[MQTT_SENT_QUEUE_ITEM_LEN+1];
    struct GtcSignInAck *ack;
    if(gtc_client.is_signin == (uint8_t)SIGN_IN_FALSE){
        memset(buf, 0, sizeof(buf));
        gtc_pack_sign_in_msg(buf);
        ack = (struct GtcSignInAck *)gtc_mqtt_send_cmd(gtc_cmd_sign_in, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);
        if (ack != NULL){
            for(uint8_t i=0; i<gtc_params.gun_cnt; i++){
                gtc_client.item[i].is_reup = 1;
            }
            
            gtc_client.is_signin = SIGN_IN_TRUE;
            callback_set_net_state(SIGN_IN_TRUE);
            
            //同步时间,需要考虑到mqtt中的等待
            if (callback_set_sys_time(ack->time) != 0){
                log(LOG_ERR, "set time err\r\n");
            }
        }
    } 
}


static int32_t is_change(struct GtcClientItem *item){
    int32_t ret = 0;
    if (item->is_reup == 1){
        item->is_reup = 0;
        ret |= 1;  
    }

    if (item->gun_status_bak.work_stat != item->gun_status.work_stat){
        ret |= 1;
        item->gun_status_bak.work_stat = item->gun_status.work_stat;
    }
    
    if (item->gun_status_bak.car_connection_stat != item->gun_status.car_connection_stat){
        ret |= 1;
        item->gun_status_bak.car_connection_stat = item->gun_status.car_connection_stat;
    }

    if (abs(item->gun_status_bak.bms_need_voltage - item->gun_status.bms_need_voltage) > 1000){
        item->gun_status_bak.bms_need_voltage = item->gun_status.bms_need_voltage;
        ret |= 1;
    }
    if (abs(item->gun_status_bak.bms_need_current - item->gun_status.bms_need_current) > 20){
        item->gun_status_bak.bms_need_current = item->gun_status.bms_need_current;
        ret |= 1;
    }  
    
    if (abs(item->gun_status_bak.current_meter_kwh_num - item->gun_status.current_meter_kwh_num) > 10){
        item->gun_status_bak.current_meter_kwh_num = item->gun_status.current_meter_kwh_num;
        ret |= 1;
    }
    
    if (abs(item->gun_status_bak.charge_power_kw - item->gun_status.charge_power_kw) > 1000){
        item->gun_status_bak.charge_power_kw = item->gun_status.charge_power_kw;
        ret |= 1;
    }
    if (abs(item->gun_status_bak.dc_charge_voltage - item->gun_status.dc_charge_voltage) > 500){
        item->gun_status_bak.dc_charge_voltage = item->gun_status.dc_charge_voltage;
        ret |= 1;
    }    
    if (abs(item->gun_status_bak.dc_charge_current - item->gun_status.dc_charge_current) > 50){
        item->gun_status_bak.dc_charge_current = item->gun_status.dc_charge_current;
        ret |= 1;
    }
 
    if (abs(item->gun_status_bak.ac_a_vol - item->gun_status.ac_a_vol) > 100){
        item->gun_status_bak.ac_a_vol = item->gun_status.ac_a_vol;
        ret |= 1;
    }
    
    if (abs(item->gun_status_bak.ac_a_cur - item->gun_status.ac_a_cur) > 50){
        item->gun_status_bak.ac_a_cur = item->gun_status.ac_a_cur;
        ret |= 1;
    } 
    
    if (item->gun_status_bak.soc_percent != item->gun_status.soc_percent ){
        item->gun_status_bak.soc_percent = item->gun_status.soc_percent;
        ret |= 1;
    }

    return ret;
}

void gtc_interval_work_for_send_gun_status(void){
    static int32_t cnt = 0;
    cnt++;
    if ((cnt % 10) != 0){
        return;
    }
    
    char_t buf[MQTT_SENT_QUEUE_ITEM_LEN+1];
    for(uint8_t i = 0; i < gtc_params.gun_cnt; i++){
        if (is_change(&gtc_client.item[i]) || (gtc_client.item[i].silent_send_gun_status_cnt > 60*10)){ //60*10
            memset(buf, 0, sizeof(buf));
            gtc_pack_dev_state_msg(&gtc_client.item[i], buf);
            
            //暂时不关心是否发送成功
            gtc_mqtt_send_cmd(gtc_cmd_status, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);
            gtc_client.item[i].silent_send_gun_status_cnt = 0;
        }else{
            gtc_client.item[i].silent_send_gun_status_cnt++;
        }
    }
}

void gtc_interval_work_for_send_bms_status(void){
    static int32_t cnt = 0;
    char_t buf[MQTT_SENT_QUEUE_ITEM_LEN+1];
    cnt++;
    if ((cnt % (10*30)) != 0){
        return;
    }

    //交流不用传bms信息
    if (gtc_params.gun_type == gtc_gun_type_ac){
        return;
    }

	for (uint8_t i = 0; i < gtc_params.gun_cnt; i++){
		if (gtc_client.item[i].gun_status.work_stat == gtc_work_stat_charging){
			memset(buf, 0, sizeof(buf));
			gtc_pack_bms_msg(&gtc_client.item[i], buf);

			//暂时不关心是否发送成功
			gtc_mqtt_send_cmd(gtc_cmd_bms, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);
		}
	}
}

void gtc_interval_work_for_histroy_bill_send(void)
{   
    static uint32_t before_time = 0;
    char_t buf[MQTT_SENT_QUEUE_ITEM_LEN+1];
    uint32_t current_time = 0;    
    uint8_t i = 0;
    
    current_time = (uint32_t)gtc_pal_time();

    if((current_time - before_time) >= 5)
    {            
        before_time = current_time;

        for(i = 0;i < MAX_HISTORY_ORDER_CNT;i++)
        {
            if(gtc_bill_ready_upload == gtc_client.histroy_bill[i].status)
            {              
                struct GtcSettleAckMsg *ack = NULL;
                memset(buf, 0, sizeof(buf));
                gtc_pack_bill_msg(&gtc_client.histroy_bill[i].bill, buf);
                ack = gtc_mqtt_send_cmd(gtc_cmd_bill_charging, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);
                if(NULL != ack)
                {
                    if(0 == strncmp(gtc_client.histroy_bill[i].bill.order_id, ack->dno,GTC_MAX_CHAEGE_USER_ID_LEN))
                    {
                        gtc_client.histroy_bill[i].status = gtc_bill_completed_Upload;
                        pal_save_history_bill(gtc_client.histroy_bill[i].bill.order_id);
                        calback_settle_set(gtc_client.histroy_bill[i].bill.gun_id, ack->total_cost);
                    }
                }
            }
        }
    }
}

void gtc_interval_work_for_bill_send(void){
    static uint32_t sent_cnt[CHARGE_GUN_CNT]={0};    
    char_t buf[MQTT_SENT_QUEUE_ITEM_LEN+1];
    static int32_t cnt = 0;

    cnt++;
    if ((cnt % (30)) != 0){  //3s一次
        return;
    }

    for(uint8_t i=0; i<gtc_params.gun_cnt; i++){
        if (gtc_client.item[i].gun_status.work_stat == gtc_work_stat_charging){

            //刚开始3s一次连续发三次，以后一分钟一次
            if ((sent_cnt[i] == 0) || (sent_cnt[i] == 1) || (sent_cnt[i]== 2) || (sent_cnt[i]== 5) || (sent_cnt[i]== 10) || ((sent_cnt[i]%20) == 0)){
                memset(buf, 0, sizeof(buf));
                gtc_pack_bill_msg(&gtc_client.item[i].current_bill, buf);
                //暂时不关心是否发送成功
                gtc_mqtt_send_cmd(gtc_cmd_bill_charging, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);

            }

            sent_cnt[i]++;
        }else{
            sent_cnt[i] = 0;
        }
    }
}

//更新历史账单  
static void gtc_updata_history_bill(struct GtcBillInfo *new_bill , enum GtcBillStatus now_status)
{
    
    uint8_t i = 0;
    uint8_t new_bill_flag = TRUE;
    
    for(i = 0;i < MAX_HISTORY_ORDER_CNT;i++)
    {
        if(gtc_bill_not_upload == gtc_client.histroy_bill[i].status)
        {
            if(0 == strncmp(gtc_client.histroy_bill[i].bill.order_id, new_bill->order_id, GTC_MAX_CHAEGE_USER_ID_LEN))
            {
                memcpy(&gtc_client.histroy_bill[i].bill, new_bill, sizeof(gtc_client.histroy_bill[i].bill));
                gtc_client.histroy_bill[i].status = now_status;
                new_bill_flag = FALSE;
                break;
            }
        }
    }

    if(TRUE == new_bill_flag)
    {
        for(i = 0; i < MAX_HISTORY_ORDER_CNT; i++)
        {
            if(gtc_bill_not_upload != gtc_client.histroy_bill[i].status && gtc_bill_ready_upload != gtc_client.histroy_bill[i].status)
            {
                    //z+++ 找到最旧的账单
                    memcpy(&gtc_client.histroy_bill[i].bill, new_bill, sizeof(gtc_client.histroy_bill[i].bill));
                    gtc_client.histroy_bill[i].status = now_status;
                    new_bill_flag = FALSE;
                    break;              
            }
        }
    }
    if(TRUE == new_bill_flag)
    {
#if XJ_LOG_RECORD_SWITCH
        xj_pal_print_log(xj_log_Error,"History bill update failure!\n");
#endif	        
    }
    
    pal_save_current_bill(new_bill); //存储到ROM中
    
}

void gtc_interval_work_for_calculate_bill_info(void)
{ 
    static struct GtcCalcBillInfoPara bill_info = {0};//账单信息参数
    uint8_t i = 0;

	bill_info.sleeped_sec++;
	
 	for(i=0; i<gtc_params.gun_cnt; i++) {		 

        struct GtcClientItem *gun = &gtc_client.item[i];
        struct GtcCalcBillInfoItem *bill = &bill_info.item[i];
    
		if(gun->gun_status.work_stat != bill->last_state 
               && gtc_work_stat_charging == gun->gun_status.work_stat) {	
 
		    bill->last_state = gtc_work_stat_charging;
			strncpy(gun->gun_status.stop_reason,"0000",sizeof(gun->gun_status.stop_reason));
			bill->last_kwh = gun->gun_status.current_meter_kwh_num;
			gun->gun_status.before_charge_meter_kwh_num = gun->gun_status.current_meter_kwh_num;
			gun->gun_status.cumulative_charge_fee = 0;
            
			gun->gun_status.start_charge_time = gtc_pal_time();

			bill->start_charge_sec = gtc_pal_time();

			memset(&gun->current_bill,0,sizeof(struct GtcBillInfo));
            strncpy(gun->current_bill.dev_id, gtc_params.dev_id, sizeof(gun->current_bill.dev_id));
			gun->current_bill.gun_id = gun->gun_status.gun_id;
			memcpy(gun->current_bill.order_id,gun->gun_status.order_id,32);
			gun->current_bill.start_soc = gun->gun_status.soc_percent;
			gun->current_bill.start_charge_kwh_meter = gun->gun_status.current_meter_kwh_num;
			gun->current_bill.charge_start_time = gtc_pal_time();
            memcpy(gun->current_bill.err_no, gun->gun_status.stop_reason, sizeof(gun->current_bill.err_no));
            memcpy(gun->current_bill.user_id, gun->gun_status.charge_user_id, GTC_MAX_CHAEGE_USER_ID_LEN);
            
#if GTC_LOG_RECORD_SWITCH
            gtc_pal_print_log(xj_log_remind,"charge started! start to calc bill. start_meter_kwh:%d\n",gun->current_bill.start_charge_kwh_meter);
#endif
		}

		if(bill->last_state == gtc_work_stat_charging)
		{
			bill->int_hour = gtc_pal_get_int_hour();
			bill->int_minute = gtc_pal_get_int_minute();		
			bill->stop_charge_sec = gtc_pal_time();
			if(bill->last_kwh >0)
			{
				bill->accum_kwh = gun->gun_status.current_meter_kwh_num - bill->last_kwh;
			}
			bill->last_kwh = gun->gun_status.current_meter_kwh_num;

			bill->index = bill->int_hour * 2;
			if(bill->int_minute >= 30)
			{
				bill->index += 1;
			}

			memcpy(gun->current_bill.order_id,gun->gun_status.order_id,32);
			gun->current_bill.charge_kwh_amount += bill->accum_kwh;
			gun->current_bill.kwh_amount[ bill->index ] += bill->accum_kwh;
			gun->current_bill.total_charge_fee += bill->accum_kwh * gtc_params.fee_config.charge_fee[ bill->index ];
			gun->current_bill.total_service_fee += bill->accum_kwh * gtc_params.fee_config.service_fee[ bill->index ];
			gun->gun_status.cumulative_charge_fee = gun->current_bill.total_charge_fee + gun->current_bill.total_service_fee;

            //printf("current kwh_amount:%d\n",gun->current_bill.charge_kwh_amount);

			gun->current_bill.end_charge_kwh_meter = gun->gun_status.current_meter_kwh_num;
			gun->current_bill.charge_end_time = gtc_pal_time();
			gun->current_bill.end_soc = gun->gun_status.soc_percent;
			gun->current_bill.charge_time = gtc_pal_time() - bill->start_charge_sec;
			gun->current_bill.start_type = 1;
			
			if(bill_info.sleeped_sec >= gtc_params.heartbeat_interval)
			{
			    gtc_updata_history_bill(&gun->current_bill,gtc_bill_not_upload);
				bill_info.sleeped_sec = 0;
			}

			if(gun->gun_status.work_stat != bill->last_state)
			{
				memcpy(gun->current_bill.err_no,gun->gun_status.stop_reason,GTC_MAX_ERR_NO_LEN);
				bill->last_state = gun->gun_status.work_stat;
				
                gtc_updata_history_bill(&gun->current_bill,gtc_bill_ready_upload);
                
				memset(&gun->current_bill,0,sizeof(struct GtcBillInfo));
				gun->gun_status.soc_percent = 0;
			}
		}
	}	
}

/*主动上报和应答消息处理*/
static void gtc_interval_work(void) {

    static uint16_t sleep = 0;   
     
    if(LOGIN_TRUE == gtc_client.is_login)
    {     	   
        gtc_interval_work_for_sign_in(); //签到      
        gtc_interval_work_for_send_gun_status();
        gtc_interval_work_for_send_bms_status();
        gtc_interval_work_for_bill_send();    //充电中账单信息发送
        gtc_interval_work_for_histroy_bill_send(); //账单发送 
    }
    
	if(sleep++ >= 10) //大约1秒更新一次账单信息
	{       
	    sleep = 0;
		gtc_interval_work_for_calculate_bill_info();//账单信息更新			
	}
}

int32_t gtc_charger_state_reup(uint32_t gun_id){
    uint8_t gun_index = gun_id-1;
    if (gun_index < CHARGE_GUN_CNT){
        gtc_client.item[gun_index].is_reup = 1;
    }
    return 0;
}

int32_t gtc_send_touch_charge_idle(uint32_t gunid){
    uint8_t gun_index = gunid-1;
    if(gun_index < CHARGE_GUN_CNT){
        strncpy(gtc_client.item[gun_index].gun_status.alarm_code, "0000", GTC_MAX_ERR_NO_LEN);
        gtc_client.item[gun_index].gun_status.work_stat = gtc_work_stat_idle;
    }
    return 0;
}


int32_t gtc_send_touch_charge_stoped(uint32_t gunid, const char_t *stop_reason) {    	
    uint8_t gun_index = gunid-1;

	if(gun_index < CHARGE_GUN_CNT)
    {
    	strncpy(gtc_client.item[gun_index].gun_status.stop_reason, stop_reason,GTC_MAX_ERR_NO_LEN);
    	sync_gun_status(gtc_client.item, gtc_client.user_gun_info,gtc_params.gun_cnt);
        if (gtc_client.item[gun_index].gun_status.work_stat == gtc_work_stat_charging){
            gtc_client.item[gun_index].gun_status.work_stat = gtc_work_stat_idle;
        }	
	}

    return -1;
}

int32_t gtc_send_touch_error_occured(uint32_t gunid, const char_t* err_no) { 
	uint8_t gun_index = gunid-1;
	if(gun_index < CHARGE_GUN_CNT && count_letter_num_len(err_no) == GTC_MAX_ERR_NO_LEN) {
        strncpy(gtc_client.item[gun_index].gun_status.alarm_code, err_no, GTC_MAX_ERR_NO_LEN);
        if (gtc_client.item[gun_index].gun_status.work_stat == gtc_work_stat_charging){
            strncpy(gtc_client.item[gun_index].gun_status.stop_reason, err_no,GTC_MAX_ERR_NO_LEN);
        }
        gtc_client.item[gun_index].gun_status.work_stat = gtc_work_stat_in_error;
        gtc_client.item[gun_index].is_reup = 1;
        return 0; 
    }
    return -1;
}

int32_t gtc_send_touch_error_recovered(uint32_t gunid, const char_t* err_no) { 
    uint8_t gun_index = gunid-1;
	if(gun_index < CHARGE_GUN_CNT && count_letter_num_len(err_no) == GTC_MAX_ERR_NO_LEN) {
    	strncpy(gtc_client.item[gun_index].gun_status.alarm_code, err_no, GTC_MAX_ERR_NO_LEN);
        gtc_client.item[gun_index].is_reup = 1;
        return 0; 
    }
    return -1;
}

//刷卡鉴权调用
int32_t gtc_send_touch_card_start_charge(uint32_t gunnum, char_t *id, char_t *pwd, uint8_t type, uint32_t value){
    if(SIGN_IN_TRUE == gtc_client.is_signin){
        char_t buf[MQTT_SENT_QUEUE_ITEM_LEN+1];
        memset(buf, 0, sizeof(buf));
        gtc_pack_card_auth_msg(gunnum, id, pwd, type, value, buf);

        gtc_mqtt_send_cmd(gtc_cmd_card_auth, buf, strlen(buf), gtc_params.network_cmd_timeout, QOS_1);
    }
    return 0;
}

#if 0 //主流程
#endif

static void restore_gtc_params(struct GtcParams *p){
	p = p;
}

static void gtc_init_params(struct GtcParams* p){
    int ver = 0;
    memset(p, 0, sizeof(struct GtcParams));
    restore_gtc_params(p);
    if (p->params_ver == 0){
        p->params_ver = 1;
    }
    if(!(p->sign_in_interval > 0 && p->sign_in_interval < 60))
    {
        p->sign_in_interval = 30;
    }
    if(!(p->network_cmd_timeout > 0 && p->network_cmd_timeout < 10))
    {
        p->network_cmd_timeout = 5;
    }
    if(!(p->upload_gun_status_interval > 0 && p->upload_gun_status_interval < 60))
    {
        p->upload_gun_status_interval = 30;
    }
    if(!(p->upload_bms_status_interval > 0 && p->upload_bms_status_interval < 60))
    {
        p->upload_bms_status_interval = 30;
    }
	if(!(p->heartbeat_interval > 0 && p->heartbeat_interval < 45))
	{
		p->heartbeat_interval = 30;
	}
	if(!(p->heartbeat_timeout_check_cnt > 0 && p->heartbeat_timeout_check_cnt < 5))
	{
		p->heartbeat_timeout_check_cnt = 3;
	}
    if(!(0 != p->gun_type))
    {
        p->gun_type = gtc_get_dev_type();
    }
    if(!(count_letter_num_len(p->dev_id) > 5))
    {
        gtc_get_devid(p->dev_id, sizeof(p->dev_id));
    }
    if(!(count_letter_num_len(p->server_addr) > 0))
    {
        gtc_get_server_addr(p->server_addr, sizeof(p->server_addr));
    }
    if(!(p->server_port > 0))
    {
        p->server_port = gtc_get_server_port();
    }

    if(!(count_letter_num_len(p->username) > 4))
    {
        strncpy(p->username,GTC_MQTT_USERNAME, GTC_MAX_USERNAME_LEN);
    }
    if(!(count_letter_num_len(p->password) > 5))
    {
        strncpy(p->password,GTC_MQTT_PASSWORD, GTC_MAX_PASSWORD_LEN);
    }
    if(!(p->gun_cnt > 0))
    {
        p->gun_cnt = pal_get_gun_cnt();
    }
    if(!(count_letter_num_len(p->mac_addr) > 0))
    {
        strncpy(p->mac_addr,GTC_MAC_ADDR,GTC_MAX_MAC_ADDR_LEN);
    }

    ver = GTC_PAL_HTONL(USER_VERSION);
    memcpy((char*)p->user_version,(char*)&ver,4);

}

static void gtc_gun_bms_status_init(uint8_t gun_cnt) {
    int32_t i = 0;   
    
    for(i=0; i<gun_cnt; i++) {
        gtc_client.item[i].gun_status.work_stat = gtc_work_stat_idle;
        gtc_client.item[i].gun_status.gun_id = i+1;
        gtc_client.item[i].bms_status.gun_id = i+1;
        strncpy(gtc_client.item[i].gun_status.alarm_code, "0000", 4);
    }
}

static int8_t gtc_init(struct ClientUserGunInfo* gun_status, struct ClientUserBmsInfo* bms_status)
{	
    assert(gun_status != NULL);
    assert(bms_status != NULL);

    gtc_client.user_gun_info = gun_status;
    gtc_client.user_bms_info = bms_status;
    //memset(_g_mqtt_resp_to_send_queue,0,sizeof(_g_mqtt_resp_to_send_queue));
    return 0;
}

void store_gtc_params(const struct GtcParams *params){

}

//开机查询历史账单  
static void gtc_read_history_bill(void) {

    if(0 == callback_read_bill(gtc_client.histroy_bill, MAX_HISTORY_ORDER_CNT)) {
        for(uint8_t i = 0; i < MAX_HISTORY_ORDER_CNT; i++) {
            if(gtc_bill_not_upload == gtc_client.histroy_bill[i].status) {
                if (strncmp(gtc_client.histroy_bill[i].bill.err_no, "0000", 4) == 0){
                    memcpy(gtc_client.histroy_bill[i].bill.err_no, "1004", 4); //异常断电，更改为后台停止充电
                }
                gtc_client.histroy_bill[i].status = gtc_bill_ready_upload;
            }
        }
    }
}


static void System_param_init(struct ClientUserGunInfo* gun_status, struct ClientUserBmsInfo* bms_status)
{          
    gtc_init_params(&gtc_params);
    gtc_gun_bms_status_init(gtc_params.gun_cnt);       
    gtc_init(gun_status, bms_status);
    store_gtc_params(&gtc_params);
    gtc_read_history_bill();
}

static int32_t center_login(void){
    return mqtt_connect();
}

static void gtc_first_login(void){

    int32_t ret;
    
    do{
        ret = center_login();
        if(ret != 0)
        {
            log(LOG_DEBUG, "login failed! retry in 5 seconds.ret=%d\n", ret);
        }
        else 
        {
            break;   
        }
        os_msleep(5*1000);
    }
    while(ret != 0);   
    gtc_client.is_login = LOGIN_TRUE;
    log(LOG_DEBUG, "login server succeeded!\n");

}

void gtc_relogin(void){
    int32_t ret = center_login();
    if (ret != 0){
        log(LOG_DEBUG, "relogin failed! retry in 5 seconds.ret=%d\n", ret);
        os_msleep(5*1000);
    }else{
        gtc_client.is_login = LOGIN_TRUE;
        log(LOG_DEBUG, "relogin server succeeded!\n");        
    }
}

void gtc_cycle_task(void *para){
    os_msleep(5000);
    gtc_first_login(); 
    while(1){
        gtc_mqtt_sycle();
        if (gtc_client.is_login == LOGIN_TRUE){
            if (mqtt_is_connect() == 0){
                gtc_client.is_login = LOGIN_FALSE;
                gtc_client.is_signin = SIGN_IN_FALSE;
                callback_set_net_state(SIGN_IN_FALSE);
            }
        }else{
            gtc_relogin();
            gtc_client.relogin_cnt++;
        }
    }
}
int32_t client_get_net_login_state(void){
    return gtc_client.is_signin;
}

uint32_t client_get_relogin_cnt(void){
    return gtc_client.relogin_cnt;
}

void gtc_cmd_task(void* args)
{
    static uint16_t thread_sec = 100;   
       
    for(;;)
    {	
        if(thread_sec++ >= 100)//1S更新一次
        {   
            thread_sec = 0;
            sync_gun_status(gtc_client.item, gtc_client.user_gun_info, gtc_params.gun_cnt);        
            sync_bms_status(gtc_client.item, gtc_client.user_bms_info, gtc_params.gun_cnt);                     
        }       
        gtc_cmd_info_handle(&gtc_client.cmd_info);
        os_msleep(10);
    }
}

void gtc_message_handle(void* args) {    
    while(1) {   
        gtc_interval_work();      
        os_msleep(100);
    }

}

int32_t client_init(struct ClientUserGunInfo* gun_status, struct ClientUserBmsInfo* bms_status)
{
    os_pthread_t client_thread;
    os_pthread_t incident_thread;
    os_pthread_t message_thread;
    
    assert(gun_status != NULL);
    assert(bms_status != NULL);
   
    memset(&gtc_client, 0, sizeof(gtc_client));
    gtc_client.is_login = LOGIN_FALSE;
    gtc_client.is_signin = SIGN_IN_FALSE;
 
    system_storage = check_cpu();
    System_param_init(gun_status,bms_status);
    pal_init();
    mqtt_init(&gtc_params);

    if (os_pthread_create("sdk-cycle", &client_thread, gtc_cycle_task, NULL, OS_TASK_PRIO_NOMAL, OS_STACK_SIZE_SUPER_LARGE) != 0) {
        return -1;
    }
    if(os_pthread_create("sdk-cmd-deal", &incident_thread, gtc_cmd_task, NULL, OS_TASK_PRIO_NOMAL, OS_STACK_SIZE_SUPER_LARGE) != 0) {
        return -1;
    }
    if(os_pthread_create("sdk-work", &message_thread, gtc_message_handle, NULL, OS_TASK_PRIO_NOMAL, OS_STACK_SIZE_SUPER_LARGE) != 0) {
        return -1;
    }

    return 0;
}

int32_t pro_client_init(void){
        
    return client_init(pal_get_user_client_gun_data(), pal_get_user_client_bms_data());
}

